<?php
/**
 * [ Random Framework ]
 *
 * @version 2.0.0 (build 20130520)
 *
 * @link http://0x00.sinaapp.com/random.html
 * 
 * @author Coseylee (Coseylee@gmail.com).
 *
 */

if (PHP_VERSION < 5) exit('The server PHP version is too low!');

final class random
{
	const VERSION = '2.0.0';
	const RELEASE = '20130520';

	private static $running = false;

	/**
	 * 框架入口
	 * 
	 * @return void
	 */
	public function __construct()
	{
		try
		{
			if (self::$running)
			{
				throw new random_exception('"Random" Class Can\'t Be Repeated Call.');
			}
			self::$running = true;

			$this -> _init();
			$this -> _config();
			$this -> _request();
			$this -> _route();
			$this -> _output();
			$this -> _start_process();
		}
		catch (Exception $e)
		{
			if (!$e instanceof random_exception)
			{
				$e = new random_exception($e -> getMessage());
			}
			exit($e); // toString
		}
	}

	/**
	 * 运行环境初始化
	 * 
	 * @return void
	 */
	private function _init()
	{
		if(PHP_VERSION < '5.3.0')
		{
			set_magic_quotes_runtime(0);
		}

		// 运行过程
		$trace = debug_backtrace();

		// 程序运行标识
		define('IN_RANDOM', true);
		// 目录分隔符
		define('DIR_SEP', DIRECTORY_SEPARATOR);
		// random 所在目录路径
		define('APP_ROOT', isset($trace[1]) ? substr($trace[1]['file'], 0, -9) : '');
		// random 目录路径
		define('RANDOM_ROOT', isset($trace[0]) ? substr($trace[0]['file'], 0, -10) : '');
		// 当前时间
		define('TIMESTAMP', $_SERVER['REQUEST_TIME']);
		// 程序开始时间
		define('STARTTIME', microtime(true));
	}
	
	/**
	 * 框架配置初始化
	 * 
	 * @return void
	 */
	private function _config()
	{
		include RANDOM_ROOT.'random.function.php';
		
		$config_path = APP_ROOT.'config'.DIR_SEP.APP_NAME;
		// 线上线上使用不同配置文件，开发环境使用 ".dev.php" 后缀。
		if (file_exists($config_path.'.config.dev.php'))
		{
			include $config_path.'.config.dev.php';
		}
		else if (file_exists($config_path.'.config.php'))
		{
			include $config_path.'.config.php';
		}
		else
		{
			exit('App Config File Not Found.');
		}
		include RANDOM_ROOT.'random.config.php';
		$GLOBALS['RANDOM'] = merge_config($random_config, $app_config);
		$GLOBALS['RANDOM']['load_file'] = $GLOBALS['RANDOM']['load_class'] = array();
		$GLOBALS['RANDOM']['route']['controller_sub_dir'] = '';
		
		// 引入必要文件
		random_runtime();
	}
		
	/**
	 * 请求初始化
	 * 
	 * @return void
	 */
	private function _request()
	{		
		$global_key = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_SERVER', '_ENV', '_FILES', 'RANDOM');
		
		foreach ($GLOBALS as $key => $value)
		{
			if (!in_array($key, $global_key))
			{
				$GLOBALS[$key] = null;
				unset($GLOBALS[$key]);
			}
		}
		
		if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
		{
			$_POST = strip_slashes($_POST);
			$_GET = strip_slashes($_GET);
			$_COOKIE = strip_slashes($_COOKIE);
			$_FILES = strip_slashes($_FILES);
		}
		
		// 请求方式
		define('REQUEST_METHOD', strtoupper($_SERVER['REQUEST_METHOD']));
		// 表单提交标识
		define('DOSUBMIT', isset($_POST['dosubmit']) ? true : false);
		
		if(REQUEST_METHOD == 'POST' && !empty($_POST))
		{
			$_POST = array_merge($_GET, $_POST);
		}
		
		// XSS
		if(REQUEST_METHOD == 'GET' && !empty($_SERVER['QUERY_STRING']))
		{
			$uri_query = strtoupper(urldecode(urldecode($_SERVER['REQUEST_URI'])));
			if(strpos($uri_query, '<') !== false || strpos($uri_query, '"') !== false || strpos($uri_query, 'CONTENT-TRANSFER-ENCODING') !== false)
			{
				throw new random_exception('Request Tainting');
			}
		}
	}

	/**
	 * 初始化路由
	 * 
	 * @return void
	 */
	private function _route()
	{
		$route_name = trim($GLOBALS['RANDOM']['route']['mode']);
		$route_class = $route_name.'_route';
		if (!class_exists($route_class))
		{
			random::import(RANDOM_ROOT.'route'.DIR_SEP.$route_name.'.route.php');
		}

		try
		{
			// 保存路由对象，在生成URL时使用
			$GLOBALS['RANDOM']['route']['router'] = self::newInstance($route_class);
		}
		catch (random_exception $e)
		{
			throw new random_exception('Router Class "'.$route_class.'" Not Found.');
		}
	}
	
	/**
	 * 输出初始化
	 * 
	 * @return void
	 */
	private function _output()
	{
		function_exists('date_default_timezone_set') && date_default_timezone_set($GLOBALS['RANDOM']['timezone']);
		$GLOBALS['RANDOM']['debug'] ? error_reporting(E_ALL) : set_error_handler('random_error_handler');
		
		if ($GLOBALS['RANDOM']['gzip'])
		{
			if (function_exists('ob_gzhandler'))
			{
				ob_start('ob_gzhandler');
			}
			else
			{
				ob_start();
			}
		}
		header('Content-Type:text/html;charset='.$GLOBALS['RANDOM']['charset']);
	}
	
	/**
	 * 开启网站进程
	 * 
	 * @return void
	 */
	private function _start_process()
	{
		// 预置挂载点: 进程准备好
		self::lanucher('process_ready');

		// 如果只希望使用基本功能，不自动开启网站进程，请指定使用 define('NO_AUTORUN', true);
		if (!defined('NO_AUTORUN'))
		{
			$controller = CONTROLLER;
			$action = ACTION;

			// 预置挂载点: 进程开始
			self::lanucher('process_start');
			
			$controller_file = $GLOBALS['RANDOM']['controller_path'].CONTORLLER_SUB_DIR.$controller.'.php';
			
			if (file_exists($controller_file))
			{
				include $controller_file;
				if (class_exists($controller))
				{
					$app = new $controller;
					if (method_exists($app, $action) && is_callable(array($app, $action)))
					{
						//call_user_func(array($app, $action));
						$app -> $action();
						unset($app);
						// 预置挂载点: 进程结束
						self::lanucher('process_end');
					}
					else
					{
						throw new random_exception('Action method does not exist.');
					}
				}
				else
				{
					throw new random_exception('Controller class does not exist.');
				}
			}
			else
			{
				throw new random_exception('Controller file not found.');
			}
		}
	}

	/**
	 * 执行挂靠点
	 * 
	 * @param $lanucher 挂靠点名称
	 * @param $args 附加参数
	 * 
	 * @return boolean
	 */
	public static function lanucher($lanucher, $args = null)
	{
		$lanucher_config = $GLOBALS['RANDOM']['lanucher'];
		if (isset($lanucher_config[$lanucher]))
		{
			foreach ($lanucher_config[$lanucher] as $func)
			{
				if (is_string($func))
				{
					eval($func.';');
				}
			}
		}
		return true;
	}
	
	/**
	 * 导入模型（支持链式操作）
	 * 
	 * @param $model 模型类名
	 * @param $init 是否重新实例化
	 * 
	 * @return object
	 */
	public static function model($model, $init = false)
	{
		$model = $model.'_model';
		$model_file = $GLOBALS['RANDOM']['model_path'].$model.'.php';
		return self::module($model, $model_file, $init);
	}

	/**
	 * 导入业务模型（支持链式操作）
	 * 
	 * @param $service 业务类名
	 * @param $init 是否重新实例化
	 * 
	 * @return object
	 */
	public static function service($service, $init = false)
	{
		$service = $service.'_service';
		$service_file = $GLOBALS['RANDOM']['service_path'].$service.'.php';
		return self::module($service, $service_file, $init);
	}
	
	/**
	 * 导入模块文件（支持链式操作）
	 * 
	 * @param $module 模块类名
	 * @param $module_file 模块文件
	 * @param $init 是否重新实例化
	 * 
	 * @return object
	 */
	public static function module($module, $module_file, $init = false)
	{
		$key = md5($module_file);
		if (isset($GLOBALS['RANDOM']['load_class'][$key]))
		{
			if ($init == false)
			{
				return $GLOBALS['RANDOM']['load_class'][$key];
			}
			else
			{
				try
				{
					return $GLOBALS['RANDOM']['load_class'][$key] = self::newInstance($module);
				}
				catch (random_exception $e)
				{
					throw new random_exception('Not Found Module Class ('.$module.')');
				}
			}
		}
		if (file_exists($module_file))
		{
			include $module_file;
			$GLOBALS['RANDOM']['load_file'][$key] = $module_file;
			try
			{
				return $GLOBALS['RANDOM']['load_class'][$key] = self::newInstance($module);
			}
			catch (random_exception $e)
			{
				throw new random_exception('Not Found Module Class ('.$module.')');
			}
		}
		throw new random_exception('Not Found Module File ('.$module.'.php)');
		return false;
	}
	
	/**
	 * 导入（第三方）文件（类）
	 * 
	 * @param $file 文件名或完整路径
	 * @param $display_error 未找到时是否显示错误
	 * 
	 * @return object
	 */
	public static function import($file, $display_error = true)
	{
		if (isset($GLOBALS['RANDOM']['load_file'][md5($file)]))
		{
			return true;
		}
		
		// 直接寻找文件
		if (file_exists($file))
		{
			include $file;
			$GLOBALS['RANDOM']['load_file'][md5($file)] = $file;
			return true;
		}
		// 搜索指定目录
		else
		{
			$search_path = array_merge(array($GLOBALS['RANDOM']['extensions_path']), $GLOBALS['RANDOM']['include_path']);
			foreach ($search_path as $path)
			{
				$temp_file = $path.$file;
				if (isset($GLOBALS['RANDOM']['load_file'][md5($temp_file)]))
				{
					return true;
				}
				else if (file_exists($temp_file))
				{
					include $temp_file;
					$GLOBALS['RANDOM']['load_file'][md5($temp_file)] = $temp_file;
					return true;
				}
			}
		}
		// 没有找到文件
		if ($display_error == true)
		{
			$file = str_replace(APP_ROOT, '', $file);
			throw new random_exception('Not Found File ('.$file.')');
		}
		return false;
	}

	/**
	 * 实例化类
	 * 
	 * @param $class 类名
	 * @param $args 类实例化参数，数组形式
	 * 
	 * @return object
	 */
	public static function newInstance($class, $args = array())
	{
		if (class_exists($class))
		{
			$rc = new ReflectionClass($class);
			return $rc -> newInstanceArgs($args);
		}
		else
		{
			throw new random_exception('Undefined Class "'.$class.'"');
		}
	}
}
